package postgres

import (
	"context"
	manager "manager/model/entity"
	"time"
)

type ebikeUnbind struct {
}

type ebikeBind struct {
}

type ebikeBind4G struct {
}
type ebikeBindBluetooth struct {
}

type ebikeLost struct {
}

type ebikeFault struct {
}

type rideDistance struct {
}

var Unbind = &ebikeUnbind{}
var Bind = &ebikeBind{}
var Bind4G = &ebikeBind4G{}
var BindBluetooth = &ebikeBindBluetooth{}
var Lost = &ebikeLost{}
var Fault = &ebikeFault{}
var RideDisntance = &rideDistance{}

// 绑定车辆
func (e *ebikeUnbind) Count(ctx context.Context) (int64, error) {
	var (
		count int64
		err   error
	)
	err = GetManagerDB(ctx).Model(&manager.Ebike{}).Where("is_bind=?", 0).Count(&count).Error
	if err != nil {
		return 0, err
	}
	return count, err
}

func (e *ebikeUnbind) CountByRange(ctx context.Context, begin, end time.Time) (DurationCount, error) {
	var (
		count DurationCount
	)
	count.Point = begin
	err := GetManagerDB(ctx).Model(&manager.Ebike{}).
		Where("is_bind= ? and created_at > ? and created_at < ?", 0, begin.Unix(), end.Unix()).Count(&count.Count).Error
	if err != nil {
		return DurationCount{}, err
	}
	return count, err
}

func (e *ebikeUnbind) ThirtyDaysCount(ctx context.Context, month time.Time) (DurationCounts, error) {
	rawSql := "SELECT DATE_TRUNC('day', to_timestamp(created_at)) AS day, COUNT(1) " +
		"from ebikes where is_bind= 0 and  created_at > ? and created_at < ? group by day"
	begin := time.Date(month.Year(), month.Month(), 1, 0, 0, 0, 0, month.Location())
	end := time.Date(month.Year(), month.Month()+1, 1, 0, 0, 0, 0, month.Location())
	now := time.Now()
	if now.Year() == month.Year() && now.Month() == month.Month() {
		end = month
	}
	return queryCount(GetManagerDB(ctx), rawSql, begin, end)
}

func (e *ebikeUnbind) TwelveMonthsCount(ctx context.Context, year time.Time) (DurationCounts, error) {
	rawSql := "SELECT DATE_TRUNC('month', to_timestamp(created_at)) AS month, COUNT(1) " +
		"from ebikes where is_bind= 0 and  created_at > ? and created_at < ? group by month"
	begin := time.Date(year.Year(), 1, 1, 0, 0, 0, 0, year.Location())
	end := time.Date(year.Year(), 12, 30, 23, 59, 59, 0, year.Location())
	return queryCount(GetManagerDB(ctx), rawSql, begin, end)
}

func (e *ebikeUnbind) FiveYearsCount(ctx context.Context, year time.Time) (DurationCounts, error) {
	rawSql := "SELECT DATE_TRUNC('year', to_timestamp(created_at)) AS year, COUNT(1) " +
		"from ebikes where is_bind= 0 and  created_at > ? and created_at < ? group by year"
	begin := time.Date(year.Year()-4, 1, 1, 0, 0, 0, 0, year.Location())
	end := time.Date(year.Year(), 12, 30, 0, 0, 0, 0, year.Location())
	return queryCount(GetManagerDB(ctx), rawSql, begin, end)
}

// 绑定车辆
func (e *ebikeBind) Count(ctx context.Context) (int64, error) {
	var (
		count int64
		err   error
	)
	err = GetManagerDB(ctx).Model(&manager.Ebike{}).Where("is_bind=?", 1).Count(&count).Error
	if err != nil {
		return 0, err
	}
	return count, err
}

func (e *ebikeBind) CountByRange(ctx context.Context, begin, end time.Time) (DurationCount, error) {
	var (
		count DurationCount
	)
	count.Point = begin
	err := GetManagerDB(ctx).Model(&manager.Ebike{}).
		Where("is_bind= ? and created_at > ? and created_at < ?", 1, begin.Unix(), end.Unix()).Count(&count.Count).Error
	if err != nil {
		return DurationCount{}, err
	}
	return count, err
}

func (e *ebikeBind) ThirtyDaysCount(ctx context.Context, month time.Time) (DurationCounts, error) {
	rawSql := "SELECT DATE_TRUNC('day', to_timestamp(created_at)) AS day, COUNT(1) " +
		"from ebikes where is_bind= 1 and  created_at > ? and created_at < ? group by day"
	begin := time.Date(month.Year(), month.Month(), 1, 0, 0, 0, 0, month.Location())
	end := time.Date(month.Year(), month.Month()+1, 1, 0, 0, 0, 0, month.Location())
	return queryCount(GetManagerDB(ctx), rawSql, begin, end)
}

func (e *ebikeBind) TwelveMonthsCount(ctx context.Context, year time.Time) (DurationCounts, error) {
	rawSql := "SELECT DATE_TRUNC('month', to_timestamp(created_at)) AS month, COUNT(1) " +
		"from ebikes where is_bind= 1 and  created_at > ? and created_at < ? group by month"
	begin := time.Date(year.Year(), 1, 1, 0, 0, 0, 0, year.Location())
	end := time.Date(year.Year(), 12, 30, 23, 59, 59, 0, year.Location())
	return queryCount(GetManagerDB(ctx), rawSql, begin, end)
}

func (e *ebikeBind) FiveYearsCount(ctx context.Context, year time.Time) (DurationCounts, error) {
	rawSql := "SELECT DATE_TRUNC('year', to_timestamp(created_at)) AS year, COUNT(1) " +
		"from ebikes where is_bind= 1 and  created_at > ? and created_at < ? group by year"
	begin := time.Date(year.Year()-4, 1, 1, 0, 0, 0, 0, year.Location())
	end := time.Date(year.Year(), 12, 30, 0, 0, 0, 0, year.Location())
	return queryCount(GetManagerDB(ctx), rawSql, begin, end)
}

// 绑定车辆 4G版本
func (e *ebikeBind4G) Count(ctx context.Context) (int64, error) {
	var (
		count int64
		err   error
	)
	row := GetManagerDB(ctx).Raw("SELECT count(1) from ebikes a inner join ebike_types b on a.type_id = b.id " +
		"where a.is_bind=1 and b.socket_type=1").Row()
	err = row.Scan(&count)
	if err != nil {
		return 0, err
	}
	return count, err
}

func (e *ebikeBind4G) CountByRange(ctx context.Context, begin, end time.Time) (DurationCount, error) {
	var (
		count DurationCount
		err   error
	)
	count.Point = begin
	err = GetManagerDB(ctx).Raw("SELECT DATE_TRUNC('day', to_timestamp(a.created_at)) AS day, COUNT(1) FROM ebikes a "+
		"inner join ebike_types b on a.type_id = b.id where created_at> ? and created_at< ? and a.is_bind= 1 and "+
		"socket_type = 1 group by day order by day;", begin.Unix(), end.Unix()).Row().Scan(&count.Count)
	if err != nil {
		return DurationCount{}, err
	}
	return count, err
}

func (e *ebikeBind4G) ThirtyDaysCount(ctx context.Context, month time.Time) (DurationCounts, error) {
	rawSql := "SELECT DATE_TRUNC('day', to_timestamp(a.created_at)) AS day, COUNT(1) FROM ebikes a " +
		"inner join ebike_types b on a.type_id = b.id where a.created_at> ? and a.created_at< ? and a.is_bind= 1 and " +
		"socket_type = 1 group by day"
	begin := time.Date(month.Year(), month.Month(), 1, 0, 0, 0, 0, month.Location())
	end := time.Date(month.Year(), month.Month()+1, 1, 0, 0, 0, 0, month.Location())
	return queryCount(GetManagerDB(ctx), rawSql, begin, end)
}

func (e *ebikeBind4G) TwelveMonthsCount(ctx context.Context, year time.Time) (DurationCounts, error) {
	rawSql := "SELECT DATE_TRUNC('month', to_timestamp(a.created_at)) AS month, COUNT(1) FROM ebikes a " +
		"inner join ebike_types b on a.type_id = b.id where a.created_at> ? and a.created_at< ? and a.is_bind= 1 and " +
		"socket_type = 1 group by month "
	begin := time.Date(year.Year(), 1, 1, 0, 0, 0, 0, year.Location())
	end := time.Date(year.Year(), 12, 30, 23, 59, 59, 0, year.Location())
	return queryCount(GetManagerDB(ctx), rawSql, begin, end)
}

func (e *ebikeBind4G) FiveYearsCount(ctx context.Context, year time.Time) (DurationCounts, error) {
	rawSql := "SELECT DATE_TRUNC('year', to_timestamp(a.created_at)) AS year, COUNT(1) FROM ebikes a " +
		"inner join ebike_types b on a.type_id = b.id where a.created_at> ? and a.created_at< ? and a.is_bind= 1 and " +
		"socket_type = 1 group by year"
	begin := time.Date(year.Year()-4, 1, 1, 0, 0, 0, 0, year.Location())
	end := time.Date(year.Year(), 12, 30, 0, 0, 0, 0, year.Location())
	return queryCount(GetManagerDB(ctx), rawSql, begin, end)
}

// 绑定车辆 蓝牙版本
func (e *ebikeBindBluetooth) Count(ctx context.Context) (int64, error) {
	var (
		count int64
		err   error
	)
	row := GetManagerDB(ctx).Raw("SELECT count(1) from ebikes a inner join ebike_types b on a.type_id = b.id " +
		"where a.is_bind=1 and  b.socket_type=0").Row()
	err = row.Scan(&count)
	if err != nil {
		return 0, err
	}
	return count, err
}

func (e *ebikeBindBluetooth) CountByRange(ctx context.Context, begin, end time.Time) (DurationCount, error) {
	var (
		count DurationCount
		err   error
	)
	count.Point = begin
	err = GetManagerDB(ctx).Raw("SELECT DATE_TRUNC('day', to_timestamp(a.created_at)) AS day, COUNT(1) FROM ebikes a "+
		"inner join ebike_types b on a.type_id = b.id where a.created_at> ? and a.created_at< ? and a.is_bind= 1 and "+
		"socket_type = 0 group by day order by day;", begin.Unix(), end.Unix()).Row().Scan(&count.Count)
	if err != nil {
		return DurationCount{}, err
	}
	return count, err
}

func (e *ebikeBindBluetooth) ThirtyDaysCount(ctx context.Context, month time.Time) (DurationCounts, error) {
	rawSql := "SELECT DATE_TRUNC('day', to_timestamp(a.created_at)) AS day, COUNT(1) FROM ebikes a " +
		"inner join ebike_types b on a.type_id = b.id where a.created_at> ? and a.created_at< ? and a.is_bind= 1 and " +
		"socket_type = 0 group by day"
	begin := time.Date(month.Year(), month.Month(), 1, 0, 0, 0, 0, month.Location())
	end := time.Date(month.Year(), month.Month()+1, 1, 0, 0, 0, 0, month.Location())
	return queryCount(GetManagerDB(ctx), rawSql, begin, end)
}

func (e *ebikeBindBluetooth) TwelveMonthsCount(ctx context.Context, year time.Time) (DurationCounts, error) {
	rawSql := "SELECT DATE_TRUNC('month', to_timestamp(a.created_at)) AS month, COUNT(1) FROM ebikes a " +
		"inner join ebike_types b on a.type_id = b.id where a.created_at> ? and a.created_at< ? and a.is_bind= 1 and " +
		"socket_type = 0 group by month "
	begin := time.Date(year.Year(), 1, 1, 0, 0, 0, 0, year.Location())
	end := time.Date(year.Year(), 12, 30, 23, 59, 59, 0, year.Location())
	return queryCount(GetManagerDB(ctx), rawSql, begin, end)
}

func (e *ebikeBindBluetooth) FiveYearsCount(ctx context.Context, year time.Time) (DurationCounts, error) {
	rawSql := "SELECT DATE_TRUNC('year', to_timestamp(a.created_at)) AS year, COUNT(1) FROM ebikes a " +
		"inner join ebike_types b on a.type_id = b.id where a.created_at> ? and a.created_at< ? and a.is_bind= 1 and " +
		"socket_type = 0 group by year"
	begin := time.Date(year.Year()-4, 1, 1, 0, 0, 0, 0, year.Location())
	end := time.Date(year.Year(), 12, 30, 0, 0, 0, 0, year.Location())
	return queryCount(GetManagerDB(ctx), rawSql, begin, end)
}

// 丢失车辆
func (e *ebikeLost) Count(ctx context.Context) (int64, error) {
	var (
		count int64
		err   error
	)
	err = GetManagerDB(ctx).Model(manager.Lose{}).Count(&count).Error
	if err != nil {
		return 0, err
	}
	return count, err
}

func (e *ebikeLost) CountByRange(ctx context.Context, begin, end time.Time) (DurationCount, error) {
	var (
		count DurationCount
		err   error
	)
	count.Point = begin
	err = GetManagerDB(ctx).Model(&manager.Lose{}).Where("created_at > ? and created_at < ?",
		begin.Unix(), end.Unix()).Count(&count.Count).Error
	if err != nil {
		return DurationCount{}, err
	}
	return count, err
}

func (e *ebikeLost) ThirtyDaysCount(ctx context.Context, month time.Time) (DurationCounts, error) {
	rawSql := "SELECT DATE_TRUNC('day', to_timestamp(created_at)) AS day, COUNT(1) FROM loses " +
		"where created_at > ? and created_at < ?  group by day"
	begin := time.Date(month.Year(), month.Month(), 1, 0, 0, 0, 0, month.Location())
	end := time.Date(month.Year(), month.Month()+1, 1, 0, 0, 0, 0, month.Location())
	return queryCount(GetManagerDB(ctx), rawSql, begin, end)
}

func (e *ebikeLost) TwelveMonthsCount(ctx context.Context, year time.Time) (DurationCounts, error) {
	rawSql := "SELECT DATE_TRUNC('month', to_timestamp(created_at)) AS month, COUNT(1) FROM loses " +
		"where created_at > ? and created_at < ?  group by month"
	begin := time.Date(year.Year(), 1, 1, 0, 0, 0, 0, year.Location())
	end := time.Date(year.Year(), 12, 30, 23, 59, 59, 0, year.Location())
	return queryCount(GetManagerDB(ctx), rawSql, begin, end)
}

func (e *ebikeLost) FiveYearsCount(ctx context.Context, year time.Time) (DurationCounts, error) {
	rawSql := "SELECT DATE_TRUNC('year', to_timestamp(created_at)) AS year, COUNT(1) FROM loses " +
		"where created_at > ? and created_at < ?  group by year"
	begin := time.Date(year.Year()-4, 1, 1, 0, 0, 0, 0, year.Location())
	end := time.Date(year.Year(), 12, 30, 0, 0, 0, 0, year.Location())
	return queryCount(GetManagerDB(ctx), rawSql, begin, end)
}

// 中控报警
func (e *ebikeFault) Count(ctx context.Context) (int64, error) {
	var (
		count int64
		err   error
	)
	err = GetManagerDB(ctx).Model(manager.Fault{}).Count(&count).Error
	if err != nil {
		return 0, err
	}
	return count, err
}

func (e *ebikeFault) CountByRange(ctx context.Context, begin, end time.Time) (DurationCount, error) {
	var (
		count DurationCount
		err   error
	)
	count.Point = begin
	err = GetManagerDB(ctx).Model(&manager.Fault{}).Where("created_at > ? and created_at < ?",
		begin.Unix(), end.Unix()).Count(&count.Count).Error
	if err != nil {
		return DurationCount{}, err
	}
	return count, err
}

func (e *ebikeFault) ThirtyDaysCount(ctx context.Context, month time.Time) (DurationCounts, error) {
	rawSql := "SELECT DATE_TRUNC('day', to_timestamp(created_at)) AS day, COUNT(1) FROM faults " +
		"where created_at > ? and created_at < ?  group by day"
	begin := time.Date(month.Year(), month.Month(), 1, 0, 0, 0, 0, month.Location())
	end := time.Date(month.Year(), month.Month()+1, 1, 0, 0, 0, 0, month.Location())
	return queryCount(GetManagerDB(ctx), rawSql, begin, end)
}

func (e *ebikeFault) TwelveMonthsCount(ctx context.Context, year time.Time) (DurationCounts, error) {
	rawSql := "SELECT DATE_TRUNC('month', to_timestamp(created_at)) AS month, COUNT(1) FROM faults " +
		"where created_at > ? and created_at < ?  group by month"
	begin := time.Date(year.Year(), 1, 1, 0, 0, 0, 0, year.Location())
	end := time.Date(year.Year(), 12, 30, 23, 59, 59, 0, year.Location())
	return queryCount(GetManagerDB(ctx), rawSql, begin, end)
}

func (e *ebikeFault) FiveYearsCount(ctx context.Context, year time.Time) (DurationCounts, error) {
	rawSql := "SELECT DATE_TRUNC('year', to_timestamp(created_at)) AS year, COUNT(1) FROM faults " +
		"where created_at > ? and created_at < ?  group by year"
	begin := time.Date(year.Year()-4, 1, 1, 0, 0, 0, 0, year.Location())
	end := time.Date(year.Year(), 12, 30, 0, 0, 0, 0, year.Location())
	return queryCount(GetManagerDB(ctx), rawSql, begin, end)
}

// 所有用户骑行总距离
func (e *rideDistance) Count(ctx context.Context) (int64, error) {
	var (
		count int64
		err   error
	)
	row := GetManagerDB(ctx).Raw("SELECT sum(mileage) from route_lists").Row()
	// 这里的单位是米
	err = row.Scan(&count)
	if err != nil {
		return 0, err
	}
	// 单位是公里
	return count, err
}

func (e *rideDistance) CountByRange(ctx context.Context, begin, end time.Time) (DurationCount, error) {
	var (
		count DurationCount
		err   error
	)
	return count, err
}

func (e *rideDistance) ThirtyDaysCount(ctx context.Context, month time.Time) (DurationCounts, error) {
	return nil, nil
}

func (e *rideDistance) TwelveMonthsCount(ctx context.Context, year time.Time) (DurationCounts, error) {
	return nil, nil
}

func (e *rideDistance) FiveYearsCount(ctx context.Context, year time.Time) (DurationCounts, error) {
	return nil, nil
}

func (e *rideDistance) MonthCount(ctx context.Context, point time.Time) (DurationCounts, error) {
	return nil, nil
}
